﻿using System;
using System.Collections.Generic;
using System.Text;
using NetDimension.Weibo;

namespace ConsoleApp
{
	class Program
	{
		/*
		 * 特别强调
		 * 运行DEMO第一步先到Properties\Settings.settings文件中修改AppKey,AppSecret及AccessToken
		 * 不修改参数不能运行DEMO，直接跑来群里问的一概不回答！
		 */
		static string AppKey = Properties.Settings.Default.AppKey;
        static string AppSecret = Properties.Settings.Default.AppSecret;

		static void Main(string[] args)
		{
			OAuth oauth = null;
            string accessToken = Properties.Settings.Default.AccessToken;
			if (string.IsNullOrEmpty(accessToken))	//判断配置文件中有没有保存到AccessToken，如果没有就进入授权流程
			{
				oauth = Authorize();

				if (!string.IsNullOrEmpty(oauth.AccessToken))
				{

					Console.WriteLine("获取AccessToken{{{0}}}成功！", oauth.AccessToken);
					Console.Write("保存Token到配置文件可以避免每次运行程序都授权，是否保存？[y/n]:");
					if (Console.ReadKey(true).Key == ConsoleKey.Y)
					{

                        Properties.Settings.Default.AccessToken = oauth.AccessToken;
						Properties.Settings.Default.Save();
						Console.WriteLine();
						Console.WriteLine("配置文件已保存。如果要撤销AccessToken请删除ConsoleApp.exe.config中AcceessToken节点中的Token值。");
					}
					else
					{
						Console.WriteLine();
						Console.WriteLine("AccessToken未保存。");
					}
				}
			}
			else//如果配置文件中保存了AccesssToken
			{
				Console.WriteLine("获取到已保存的AccessToken{{{0}}}！", accessToken);
				oauth = new OAuth(AppKey, AppSecret, accessToken, "");	//用Token实例化OAuth无需再次进入验证流程
				Console.WriteLine("验证Token有效性...");
				TokenResult result = oauth.VerifierAccessToken();	//测试保存的AccessToken的有效性
				if (result == TokenResult.Success)
				{
					Console.WriteLine("AccessToken有效！");
					Console.Write("删除已保存的AccessToken可以再下次运行程序时演示授权过程，是否删除？[y/n]:");
					if (Console.ReadKey(true).Key == ConsoleKey.Y)
					{
						//如果想演示下登录授权，那就得把配置文件中的Token删除，所以做那么一个判断。
                        Properties.Settings.Default.AccessToken = string.Empty;
						Properties.Settings.Default.Save();
						Console.WriteLine();
						Console.WriteLine("已从配置文件移除AccessToken值，重新运行程序来演示授权过程。");
					}
					else
					{
						Console.WriteLine();
						Console.WriteLine("继续执行。");
					}
				}
				else
				{
					Console.WriteLine("AccessToken无效！因为：{0}", result);
                    Properties.Settings.Default.AccessToken = string.Empty;
					Properties.Settings.Default.Save();
					Console.WriteLine("已从配置文件移除AccessToken值，重新运行程序获取有效的AccessToken");
					return; //AccessToken无效，继续执行没有任何意义，反正也无法调用API
				}
			}


			//好吧，授权至此应该成功了。下一步调用接口吧。
			Client Sina = new Client(oauth);

			try
			{
				//这里注意，.Net4.0的SDK和其他版本的SDK调用API的时候稍有不同
				//.Net4.0
#if NET40
				
				string uid = Sina.API.Entity.Account.GetUID();	//这里通过Entity命名空间直接获取string型的uid，比dynamic方式要少一个步骤。所以说在项目中，根据实际情况分别调用Dynamic和Entity下面的接口，将给开发带来很大帮助。

				//下面用两种不同的返回类型来演示同一个功能

				//Dynamic版本
				Console.WriteLine(">>>>> 来自Dynamic, 动态类型 <<<<<");
				//dynamic_userInfo是dynamic类型
				var dynamic_userInfo = Sina.API.Dynamic.Users.Show(uid);
				//返回结果的结构请看：http://open.weibo.com/wiki/2/users/show
				Console.WriteLine("昵称：{0}", dynamic_userInfo.screen_name);
				Console.WriteLine("来自：{0}", dynamic_userInfo.location);
				//实体类版本，实体类的返回类型和下面代码中.net其他版本的返回类型和调用方式一致。
				Console.WriteLine(">>>>> 来自Entity, 实体类 <<<<<");
				//entity_userInfo是class，这里返回的是NetDimension.Weibo.Entities.user.Entity类型
				var entity_userInfo = Sina.API.Entity.Users.Show(uid);
				//调用方法与.Net其他版本一致，可以看下下面2.0的代码
				Console.WriteLine("昵称：{0}", entity_userInfo.ScreenName);
				Console.WriteLine("来自：{0}", entity_userInfo.Location);

				//发条微博啥的
				var statusInfo = Sina.API.Entity.Statuses.Update(string.Format("我是{0}，我来自{1}，我在{2}用《新浪微博开放平台API for .Net SDK》开发了一个小程序并发了这条微博，欢迎关注http://weibosdk.codeplex.com/", entity_userInfo.ScreenName, entity_userInfo.Location, DateTime.Now.ToShortTimeString()));
				//加个当前时间防止重复提交报错。

				Console.WriteLine("微博已发送，发送时间：{0}", statusInfo.CreatedAt);

#else
				//.Net其他版本
				string uid = Sina.API.Account.GetUID();	//获取UID
				//这里用VS2010的var关键字和可选参数最惬意了。
				//如果用VS2005什么的你得这样写：
				//NetDimension.Weibo.Entities.user.Entity userInfo = Sina.API.Users.Show(uid,null);
				//如果用VS2008什么的也不方便，你得把参数写全：
				//var userInfo = Sina.API.Users.Show(uid,null);
				var userInfo = Sina.API.Users.Show(uid);
				Console.WriteLine("昵称：{0}", userInfo.ScreenName);
				Console.WriteLine("来自：{0}", userInfo.Location);

				//发条微博啥的

				var statusInfo = Sina.API.Statuses.Update(string.Format("我是{0}，我来自{1}，我在{2}用《新浪微博开放平台API for .Net SDK》开发了一个小程序并发了这条微博，欢迎关注http://weibosdk.codeplex.com/", userInfo.ScreenName, userInfo.Location, DateTime.Now.ToShortTimeString()));
				//加个当前时间防止重复提交报错。

				Console.WriteLine("微博已发送，发送时间：{0}", statusInfo.CreatedAt);
				
#endif
			}
			catch (WeiboException ex)
			{
				Console.WriteLine("出错啦！"+ex.Message);
			}

			Console.Write("演示结束，按任意键继续...");
			Console.ReadKey();
		}

		static OAuth Authorize()
		{
            OAuth o = new OAuth(Properties.Settings.Default.AppKey, Properties.Settings.Default.AppSecret, Properties.Settings.Default.CallbackUrl);

			//让使用者自行选择一个授权方式
			Console.WriteLine("请选择授权模式");
			Console.WriteLine("1. 标准授权方式");
			Console.WriteLine("2. 模拟授权方式");//一键授权登录
			ConsoleKeyInfo key = Console.ReadKey(true);
			Console.WriteLine();
			if (key.Key == ConsoleKey.D2)
			{
				while (!ClientLogin(o))	//使用模拟方法
				{
					Console.WriteLine("授权登录失败，请重试。");
				}

			}
			else
			{
				string authorizeUrl = o.GetAuthorizeURL();
				System.Diagnostics.Process.Start(authorizeUrl);
				Console.Write("复制浏览器中的Code:");
				string code = Console.ReadLine();
				try
				{
					AccessToken accessToken = o.GetAccessTokenByAuthorizationCode(code); //请注意这里返回的是AccessToken对象，不是string
				}
				catch (WeiboException ex)
				{
					Console.WriteLine(ex.Message);
				}
			}
			return o;
		}

		private static bool ClientLogin(OAuth o)
		{
			Console.Write("微博账号:");
			string passport = Console.ReadLine();
			Console.Write("登录密码:");

			ConsoleColor originColor = Console.ForegroundColor;
			Console.ForegroundColor = Console.BackgroundColor; //知道这里是在干啥不？其实是为了不让你们看到我的密码^_^

			string password = Console.ReadLine();

			Console.ForegroundColor = originColor; //恢复前景颜色。

			return o.ClientLogin(passport, password);
		}
	}
}
